package datamining.visualisation;

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Properties;

import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

import datamining.algorithms.prefixspan.PrefixSpan;
import datamining.algorithms.prefixspan.PrefixSpanSequenceFactory;
import datamining.main.Miner;
import datamining.miner.general.Fragment;
import datamining.sequence.HPSequence;
import datamining.sequence.Sequence;
import datamining.sequence.SequenceFactory;
import datamining.strategy.RecursiveStrategy;


import settings.Settings;
import utils.PropertiesConfig;

/** 
 * 创建于 2012-11-21 上午11:18:36
 * 
 * @author xujinghu (jinghuxu@nudt.edu.cn)
 * 
 * Copyright 2012 xujinghu
 * 
 * Lisence: Apache
 */
public class MainFrame<ItemType> extends JFrame implements ActionListener,PropertyChangeListener {
	
	
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Settings settings = null;
	private JPanel mainPane = null;
	private ControlTabbedPanel controlTabbedPanel;
	private ViewTabbedPanel viewTabbedPanel;
	private StepForwardTabbedPanel stepForwardTabbedPane;
	private boolean setColor = true;
	private MainMenu menu;
	private StatusPanel statusPanel;
	int algoIndex = 0;
	Properties props = null;
	
	private ArrayList<Sequence<ItemType>> parsedSequences = null;	//输入数据的内部表示
	private ArrayList<HPSequence> freqHPSequences;	//挖掘出的频繁序列
	
	public MainFrame(Settings settings){
		this.settings = settings;
		props = PropertiesConfig.newProperties("conf/ui.properties");
		
		JFrame.setDefaultLookAndFeelDecorated(true);

		// Create and set up the window.
		System.out.println(settings.resourceDir + settings.logoFile);
		setIconImage(new ImageIcon(settings.resourceDir + settings.logoFile)
				.getImage());
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		getContentPane().add(createPanel(), BorderLayout.CENTER);
		setSize(800, 600);

		// Display the window.
		setVisible(true);
		setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
	@Override
	public void actionPerformed(ActionEvent event) {
		// TODO Auto-generated method stub
		final String command = event.getActionCommand();
		System.err.println(this.getClass().getName() + " action performed " + command);
		
		
		if (command.equals(UIEvents.start)) {	//开始搜索
			mainPane.remove(viewTabbedPanel);
			mainPane.remove(stepForwardTabbedPane);
			mainPane.add(viewTabbedPanel, BorderLayout.CENTER);
			
			final Thread t = miningThread();
			t.start();
		}else if(command.equals(UIEvents.search_done)) {	//搜索完成
			firePropertyChange(UIEvents.search_done,
					null, null);
			firePropertyChange(UIEvents.enable, null, null);
		}else if (command.equals(props.getProperty("button_show"))) {	//展示输入序列
			actionPerformed(new ActionEvent(this, 0, UIEvents.search_done));
		}
	}
	
	
	private JComponent createPanel() {
		final BorderLayout bl = new BorderLayout();
		JPanel mainPane = new JPanel(bl);
		mainPane.add(getTopPanel(), BorderLayout.NORTH);	//顶部面板，负责输入和展示状态

		controlTabbedPanel = getControlTabbedPanel();	//控制面板，负责设置参数
		mainPane.add(controlTabbedPanel, BorderLayout.WEST);

		viewTabbedPanel = getViewTabbedPanel();	//展示挖掘结果面板
		mainPane.add(viewTabbedPanel, BorderLayout.CENTER);
		
		stepForwardTabbedPane = getStepForwardTabbedPanel();	//多步挖掘面板
		firePropertyChange(UIEvents.colored, !setColor , setColor);

		return mainPane;
	}

	private ControlTabbedPanel getControlTabbedPanel(){
		ControlTabbedPanel controlTabbedPanel = new ControlTabbedPanel(props);
		this.addPropertyChangeListener(UIEvents.running,
				controlTabbedPanel);
		this.addPropertyChangeListener(UIEvents.search_done,
				controlTabbedPanel);
		controlTabbedPanel.addPropertyChangeListener(UIEvents.start, this);
		
		return controlTabbedPanel;
	}
	
	private StepForwardTabbedPanel getStepForwardTabbedPanel(){
		StepForwardTabbedPanel multiTabbedPane = new StepForwardTabbedPanel(props);
		
		return multiTabbedPane;
	}
	
	private JPanel getTopPanel() {
		final GridBagLayout gb = new GridBagLayout();
		final GridBagConstraints constraints = new GridBagConstraints();

		final JPanel topPanel = new JPanel(gb);
		menu = new MainMenu(props);
		menu.addPropertyChangeListener(this);
		this.addPropertyChangeListener("add save button", menu);

		constraints.gridx = 0;
		constraints.gridy = 0;
		constraints.weightx = 0.5;
		constraints.fill = GridBagConstraints.HORIZONTAL;
		constraints.anchor = GridBagConstraints.FIRST_LINE_START;
		constraints.gridwidth = GridBagConstraints.REMAINDER;
		gb.setConstraints(menu, constraints);
		topPanel.add(menu);

		statusPanel = new StatusPanel(props);
		this.addPropertyChangeListener("set text", statusPanel);
		this.addPropertyChangeListener("set status", statusPanel);
		this.addPropertyChangeListener("set language properties", statusPanel);
		constraints.gridx = 0;
		constraints.gridy = 1;
		constraints.insets = new Insets(10, 5, 10, 0);
		constraints.anchor = GridBagConstraints.LAST_LINE_START;
		gb.setConstraints(statusPanel, constraints);
		topPanel.add(statusPanel);

		return topPanel;
	}
	
	private ViewTabbedPanel getViewTabbedPanel(){
		ViewTabbedPanel tabbedPane = new ViewTabbedPanel(props);
		this.addPropertyChangeListener(UIEvents.add_sequences, tabbedPane);
		this.addPropertyChangeListener(UIEvents.empty_tab, tabbedPane);
		
		return tabbedPane;
	}

	/**
	 * 挖掘线程
	 * @author xujinghu
	 * @date 2012-11-15上午11:08:15
	 * @return 
	 */
	private Thread miningThread() {
		final Thread t = new Thread() {

			@Override
			public void run() {
				Settings<ItemType> settings = new Settings<ItemType>("conf/config.properties"); 

				// TODO set algorithms type for the mining
				switch (settings.algoName) {
				case "prefixSpan":
					settings.algorithm = new PrefixSpan<ItemType>();
					settings.strategy = new RecursiveStrategy();
					settings.factory = new PrefixSpanSequenceFactory<ItemType>();
					break;
				default:
					settings.algorithm = new PrefixSpan<ItemType>();
				}

				Collection<Fragment<ItemType>> fragments = Miner
						.mine(parsedSequences,new PrefixSpanSequenceFactory<ItemType>(), settings);//挖掘频繁序列
				
				Collection<Sequence<ItemType>> sequences = new ArrayList<Sequence<ItemType>>();//TODO:转换挖掘出的fragments为sequences
				for(Fragment<ItemType> frag : fragments){
					sequences.add(frag.toSequence());
				}
				
				
				freqHPSequences = new ArrayList<HPSequence>();
				for (Iterator<Sequence<ItemType>> it = parsedSequences.iterator(); it.hasNext();) {//TODO:测试，直接将原始输入作为输出
					final Sequence<ItemType> seq = (Sequence<ItemType>) it.next();
					freqHPSequences.add(new HPSequence<ItemType>(seq));
				}
				
				viewTabbedPanel.setSequences(freqHPSequences);
				
				if (freqHPSequences.size() == 0) {//挖掘的结果为空，则显示空tab页
					firePropertyChange(UIEvents.empty_tab, null,
							null);
				} else {//否则对结果进行显示
					firePropertyChange(UIEvents.add_sequences, null,
							null);
				}
				actionPerformed(new ActionEvent(this, 0, UIEvents.search_done));//通知其它部件此次挖掘操作完成
				
				System.out.println("频繁序列为：\n" + sequences);
			}

		};

		return t;
	}

	/**
	 * 数据转换线程
	 * @author xujinghu
	 * @date 2012-11-15上午11:08:30
	 * @return 
	 */
	private Thread parseSeqThread() {
		final Thread t = new Thread() {
			@Override
			public void run() {
				Settings settings = new Settings("conf/config.properties"); 
				parsedSequences = Miner.parseInput(settings);
			}
		};

		return t;
	}
	
	@Override
	public void propertyChange(PropertyChangeEvent event) {
		final String propertyName = event.getPropertyName();
		System.err.println(this.getClass().getName()
				+ " property changed " + propertyName);
		
		if (propertyName == UIEvents.openFile) {	//打开文件
			final Thread thread_parse = parseSeqThread();
			thread_parse.start();
		}
		
		if (propertyName == UIEvents.start) {	//开始搜索
			final Thread thread_mining = miningThread();
			thread_mining.start();
		}
	}
	
}
